using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Matrix.Configuration.Events;
using Matrix.Configuration.Services;

namespace Matrix.Application.Services
{
    /// <summary>
    /// 配置事件策略解析器实现
    /// 负责智能选择本地事件或分布式事件
    /// </summary>
    public class ConfigurationEventStrategyResolver : IConfigurationEventStrategyResolver, ITransientDependency
    {
        private readonly ILogger<ConfigurationEventStrategyResolver> _logger;
        private readonly IOptions<ConfigurationEventOptions> _options;

        public ConfigurationEventStrategyResolver(
            ILogger<ConfigurationEventStrategyResolver> logger,
            IOptions<ConfigurationEventOptions> options)
        {
            _logger = logger;
            _options = options;
        }

        public bool ShouldUseLocalEvent(ConfigurationChangedEto eventData)
        {
            if (eventData == null)
            {
                return false;
            }

            var strategy = _options.Value.DistributionStrategy;

            // 1. 关键配置强制使用分布式事件
            if (IsCriticalConfiguration(eventData.Key, eventData.Category, eventData.Namespace))
            {
                _logger.LogDebug("关键配置使用分布式事件: Key: {Key}, Category: {Category}",
                    eventData.Key, eventData.Category);
                return false;
            }

            // 2. 根据重要性级别决定
            var importanceScore = GetImportanceScore(eventData.Importance);

            if (importanceScore >= strategy.DistributedEventThreshold)
            {
                _logger.LogDebug("高重要性配置使用分布式事件: Key: {Key}, Importance: {Importance}",
                    eventData.Key, eventData.Importance);
                return false;
            }

            if (importanceScore <= strategy.LocalEventThreshold)
            {
                _logger.LogDebug("低重要性配置使用本地事件: Key: {Key}, Importance: {Importance}",
                    eventData.Key, eventData.Importance);
                return true;
            }

            // 3. 根据配置键模式判断
            if (IsLocalServiceConfiguration(eventData.Key))
            {
                _logger.LogDebug("本地服务配置使用本地事件: Key: {Key}", eventData.Key);
                return true;
            }

            // 4. 根据配置分类判断
            if (IsCacheConfiguration(eventData.Category))
            {
                _logger.LogDebug("缓存配置使用本地事件: Key: {Key}, Category: {Category}",
                    eventData.Key, eventData.Category);
                return true;
            }

            // 5. 根据变更来源判断
            if (IsLocalChangeSource(eventData.ChangeSource))
            {
                _logger.LogDebug("本地变更来源使用本地事件: Key: {Key}, Source: {Source}",
                    eventData.Key, eventData.ChangeSource);
                return true;
            }

            // 6. 根据租户判断（单租户配置使用本地事件）
            if (!eventData.TenantId.HasValue || eventData.TenantId.Value == Guid.Empty)
            {
                _logger.LogDebug("全局配置使用本地事件: Key: {Key}", eventData.Key);
                return true;
            }

            // 7. 默认使用分布式事件
            _logger.LogDebug("默认使用分布式事件: Key: {Key}", eventData.Key);
            return false;
        }

        public bool ShouldUseLocalEvent(ConfigurationBatchChangedEto batchEventData)
        {
            if (batchEventData == null || !batchEventData.Changes.Any())
            {
                return false;
            }

            var changes = batchEventData.Changes;

            // 1. 如果有关键配置变更，使用分布式事件
            if (changes.Any(c => IsCriticalConfiguration(c.Key, c.Category, c.Namespace)))
            {
                _logger.LogDebug("批量变更包含关键配置，使用分布式事件: {ChangeCount}个变更",
                    changes.Count);
                return false;
            }

            // 2. 根据最高重要性级别决定
            var maxImportance = changes.Max(c => c.Importance);
            var importanceScore = GetImportanceScore(maxImportance);

            if (importanceScore >= _options.Value.DistributionStrategy.DistributedEventThreshold)
            {
                _logger.LogDebug("批量变更包含高重要性配置，使用分布式事件: MaxImportance: {Importance}",
                    maxImportance);
                return false;
            }

            // 3. 如果都是本地服务配置，使用本地事件
            if (changes.All(c => IsLocalServiceConfiguration(c.Key)))
            {
                _logger.LogDebug("批量变更全为本地服务配置，使用本地事件: {ChangeCount}个变更",
                    changes.Count);
                return true;
            }

            // 4. 根据变更比例决定
            var localEventCount = changes.Count(c => ShouldUseLocalEvent(c));
            var localEventRatio = (double)localEventCount / changes.Count;

            if (localEventRatio >= _options.Value.DistributionStrategy.LocalEventThreshold)
            {
                _logger.LogDebug("批量变更本地事件比例高，使用本地事件: Ratio: {Ratio:P2}",
                    localEventRatio);
                return true;
            }

            // 5. 默认使用分布式事件
            _logger.LogDebug("批量变更默认使用分布式事件: {ChangeCount}个变更", changes.Count);
            return false;
        }

        public int GetEventPriority(ConfigurationChangedEto eventData)
        {
            if (eventData == null)
            {
                return 0;
            }

            var basePriority = GetImportanceScore(eventData.Importance) * 100;

            // 关键配置额外增加优先级
            if (IsCriticalConfiguration(eventData.Key, eventData.Category, eventData.Namespace))
            {
                basePriority += 50;
            }

            // 紧急变更来源增加优先级
            if (eventData.ChangeSource == ConfigurationChangeSource.SystemUpdate)
            {
                basePriority += 20;
            }

            // 敏感配置增加优先级
            if (eventData.IsSensitive)
            {
                basePriority += 30;
            }

            return (int)Math.Round(basePriority);
        }

        public string GetEventRoutingKey(ConfigurationChangedEto eventData)
        {
            if (eventData == null)
            {
                return "config.changed.unknown";
            }

            var routingKey = $"config.changed.{eventData.Namespace.ToLowerInvariant()}";

            if (!string.IsNullOrEmpty(eventData.Category))
            {
                routingKey += $".{eventData.Category.ToLowerInvariant()}";
            }

            routingKey += $".{eventData.Importance.ToString().ToLowerInvariant()}";

            return routingKey;
        }

        public bool IsCriticalConfiguration(string key, string category, string @namespace)
        {
            if (string.IsNullOrEmpty(key))
            {
                return false;
            }

            var strategy = _options.Value.DistributionStrategy;

            // 1. 检查配置分类
            if (!string.IsNullOrEmpty(category) && strategy.CriticalConfigCategories.Contains(category))
            {
                return true;
            }

            // 2. 检查配置键模式
            var criticalKeyPatterns = new[]
            {
                "connectionstring",
                "database.connection",
                "security.*",
                "auth.*",
                "secret.*",
                "privatekey.*",
                "certificate.*",
                "token.*",
                "jwt.*",
                "oauth.*",
                "encryption.*",
                "api.key",
                "service.key"
            };

            if (criticalKeyPatterns.Any(pattern => IsKeyMatch(key, pattern)))
            {
                return true;
            }

            // 3. 检查命名空间
            var criticalNamespaces = new[]
            {
                "Security",
                "Authentication",
                "Database",
                "Infrastructure",
                "System"
            };

            if (!string.IsNullOrEmpty(@namespace) && criticalNamespaces.Contains(@namespace, StringComparer.OrdinalIgnoreCase))
            {
                return true;
            }

            return false;
        }

        private double GetImportanceScore(ConfigurationImportanceLevel importance)
        {
            return importance switch
            {
                ConfigurationImportanceLevel.Low => 0.25,
                ConfigurationImportanceLevel.Medium => 0.5,
                ConfigurationImportanceLevel.High => 0.75,
                ConfigurationImportanceLevel.Critical => 1.0,
                _ => 0.25
            };
        }

        private bool IsLocalServiceConfiguration(string key)
        {
            if (string.IsNullOrEmpty(key))
            {
                return false;
            }

            var patterns = _options.Value.DistributionStrategy.LocalServiceKeyPatterns;

            return patterns.Any(pattern => IsKeyMatch(key, pattern));
        }

        private bool IsCacheConfiguration(string category)
        {
            if (string.IsNullOrEmpty(category))
            {
                return false;
            }

            return _options.Value.DistributionStrategy.CacheConfigCategories
                .Contains(category, StringComparer.OrdinalIgnoreCase);
        }

        private bool IsLocalChangeSource(ConfigurationChangeSource source)
        {
            return source switch
            {
                ConfigurationChangeSource.ConfigurationFile => true,
                ConfigurationChangeSource.EnvironmentVariable => true,
                ConfigurationChangeSource.SystemUpdate => true,
                _ => false
            };
        }

        private bool IsKeyMatch(string key, string pattern)
        {
            if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(pattern))
            {
                return false;
            }

            // 简单的通配符匹配
            if (pattern.Contains('*'))
            {
                var regexPattern = pattern.Replace("*", ".*");
                return System.Text.RegularExpressions.Regex.IsMatch(key, $"^{regexPattern}$", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            }

            return string.Equals(key, pattern, StringComparison.OrdinalIgnoreCase);
        }
    }
}